from datetime import datetime
import os

from django.conf import settings
from rest_framework.viewsets import ModelViewSet
from rest_framework import permissions, status
from rest_framework.decorators import action
from rest_framework.response import Response

from envs.models import Envs
from modulars.models import Modulars
from testcases.models import Testcases
from utils import common
from .utils import read_cron
from .models import Tasks
from tasks import serializers


def run_cron(pk):
    cron = Tasks.objects.filter(id=pk).first()
    env_id = cron.env_id  # 获取环境变量env_id
    # 创建测试用例所在目录名
    testcase_dir_path = os.path.join(settings.SUITES_DIR,
                                     datetime.strftime(datetime.now(), '%Y%m%d%H%M%S%f'))
    if not os.path.exists(testcase_dir_path):
        os.mkdir(testcase_dir_path)
    env = Envs.objects.filter(id=env_id, is_delete=False).first()
    include = eval(cron.caseset)
    if len(include) == 0:
        data_dict = {
            'detail': '此任务下未添加用例无法运行！'
        }
        return Response(data_dict, status=status.HTTP_400_BAD_REQUEST)
    for testcase_id in include:
        testcase_obj = Testcases.objects.filter(is_delete=False, id=testcase_id).first()
        if testcase_obj:
            common.generate_testcase_files(testcase_obj, env, testcase_dir_path)
    # 运行任务
    return common.run_testcase_and_reports(cron, testcase_dir_path)


class TasksViewSet(ModelViewSet):
    """
    list:
    返回任务(多个)数据

    create:
    创建任务

    retrieve:
    返回任务(单个)详情数据

    update:
    更新(全部)任务

    partial_update:
    更新(部分)任务

    destroy:
    删除任务

    mcases:
    获取项目下的所有模块及用例

    run:
    运行任务
    """
    queryset = Tasks.objects.filter(is_delete=False)
    serializer_class = serializers.TasksModelSerializer
    permission_classes = [permissions.IsAuthenticated,]
    ordering_fields = ('id', 'name')

    def update(self, request, *args, **kwargs):
        response = super().update(request, *args, **kwargs)
        read_cron()
        os.system("python manage.py crontab remove")  # 清除定时任务
        os.system("python manage.py crontab add")  # 添加定时任务
        os.system("python manage.py crontab show")  # 显示定时任务
        return response

    def create(self, request, *args, **kwargs):
        response = super().create(request, *args, **kwargs)
        read_cron()
        os.system("python manage.py crontab remove")  # 清除定时任务
        os.system("python manage.py crontab add")  # 添加定时任务
        os.system("python manage.py crontab show")  # 显示定时任务
        return response

    def partial_update(self, request, *args, **kwargs):
        response = super().partial_update(request, *args, **kwargs)
        read_cron()
        os.system("python manage.py crontab remove")  # 清除定时任务
        os.system("python manage.py crontab add")  # 添加定时任务
        os.system("python manage.py crontab show")  # 显示定时任务
        return response

    def perform_destroy(self, instance):
        instance.is_delete = True
        instance.save()     # 逻辑删除

    @action(methods=['get'], detail=True)
    def p_models_and_cases(self, request, pk=None):
        modula_objs = Modulars.objects.filter(is_delete=False, project=pk)
        if not modula_objs.exists():
            data_dict = {
                'detail': '此项目下无功能'
            }
            return Response(data_dict, status=status.HTTP_400_BAD_REQUEST)
        one_list = []
        i = 0
        for m_obj in modula_objs:
            one_list.append({
                'mid': m_obj.id,
                'name': m_obj.name
            })
            one2_list = []
            testcase_objs = Testcases.objects.filter(is_delete=False, modular=m_obj)
            for obj in testcase_objs:
                one2_list.append({
                    'cid': obj.id,
                    'name': obj.name
                })
            one_list[i]["children"] = one2_list
            i+=1
        return Response(data=one_list)

    @action(methods=['post'], detail=True)
    def run(self, request, pk=None):
        instance = self.get_object()
        serializer = self.get_serializer(instance, data=request.data)
        serializer.is_valid(raise_exception=True)
        datas = serializer.validated_data
        env_id = datas.get('env_id')    # 获取环境变量env_id

        # 创建测试用例所在目录名
        testcase_dir_path = os.path.join(settings.SUITES_DIR,
                                         datetime.strftime(datetime.now(), '%Y%m%d%H%M%S%f'))
        if not os.path.exists(testcase_dir_path):
            os.mkdir(testcase_dir_path)
        env = Envs.objects.filter(id=env_id, is_delete=False).first()
        include = eval(instance.caseset)
        if len(include) == 0:
            data_dict = {
                'detail': '此任务下未添加用例无法运行！'
            }
            return Response(data_dict, status=status.HTTP_400_BAD_REQUEST)
        for testcase_id in include:
            testcase_obj = Testcases.objects.filter(is_delete=False, id=testcase_id).first()
            if testcase_obj:
                common.generate_testcase_files(testcase_obj, env, testcase_dir_path)
        # 运行任务
        return common.run_testcase(instance, testcase_dir_path)

    def get_serializer_class(self):
        """
        不同的action选择不同的序列化器
        :return:
        """
        return serializers.TasksRunSerializer if self.action == 'run' else serializers.TasksModelSerializer
